package model

import (
	"context"
	app "im-demo/application"
	"im-demo/util"
	"time"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

var friendRequestCollecttion *mongo.Collection

type FriendRequest struct {
	OwnerId    string `json:"owner_id" form:"owner_id" bson:"owner_id"`
	OtherId    string `json:"other_id" form:"other_id" bson:"other_id"`
	Answer     string `json:"answer" form:"answer" bson:"answer"`
	Verify     string `json:"verify" form:"verify" bson:"verify"`
	State      int8   `json:"state" form:"state" bson:"state"`
	IsRead     int8   `json:"is_read" form:"is_read" bson:"is_read"`
	CreateTime int64  `json:"create_time" form:"create_time" bson:"create_time"`
}

type FriendForm struct {
	OwnerId string `json:"owner_id" form:"owner_id"`
	OtherId string `json:"other_id" form:"other_id"`
	Answer  string `json:"answer" form:"answer"`
	Verify  string `json:"verify" form:"verify"`
}

func init() {
	friendRequestCollecttion = app.MongoDBClient.Database(app.MongoDataBaseName).Collection(app.MongoFriendRequestCollection)
}

// CreateFriendRequest 创建好友申请记录
func CreateFriendRequest(req FriendForm) error {
	createData := FriendRequest{
		OwnerId:    req.OwnerId,
		OtherId:    req.OtherId,
		Answer:     req.Answer,
		Verify:     req.Verify,
		State:      0,
		IsRead:     0,
		CreateTime: time.Now().Unix(),
	}

	filter := bson.M{
		"owner_id": req.OwnerId,
		"other_id": req.OtherId,
	}

	result := friendRequestCollecttion.FindOne(context.TODO(), filter)
	if err := result.Err(); err != nil {
		if err == mongo.ErrNoDocuments {
			_, err := friendRequestCollecttion.InsertOne(context.TODO(), createData)
			return err
		}
		return err
	}

	updateDate := bson.M{
		"$set": bson.M{
			"answer":      req.Answer,
			"verify":      req.Verify,
			"state":       0,
			"is_read":     0,
			"create_time": time.Now().Unix(),
		},
	}

	_, err := friendRequestCollecttion.UpdateOne(context.TODO(), filter, updateDate)

	return err
}

type FriendRequestInfo struct {
	Req  FriendRequest `json:"req"`  // 好友请求
	User User          `json:"user"` // 好友信息
}

// GetOwnerFriendRequest 获取好友请求列表
func GetOwnerFriendRequest(ownerId string) ([]FriendRequestInfo, error) {
	options := options.Find()
	options.SetSort(bson.D{primitive.E{Key: "state", Value: 1}, primitive.E{Key: "create_time", Value: -1}})

	filter := bson.M{
		"other_id": ownerId,
	}

	cur, err := friendRequestCollecttion.Find(context.TODO(), filter, options)
	if err != nil {
		return nil, err
	}
	defer cur.Close(context.TODO())

	userList := make([]FriendRequestInfo, 0)
	for cur.Next(context.TODO()) {
		var reqinfo FriendRequest
		err := cur.Decode(&reqinfo)
		if err != nil {
			continue
		}
		userinfo, err := GetUserInfo(reqinfo.OwnerId)
		if err != nil {
			continue
		}
		info := FriendRequestInfo{
			Req:  reqinfo,
			User: userinfo,
		}
		userList = append(userList, info)
	}

	return userList, nil
}

// AgreeFriendRequest 同意好友申请
func AgreeFriendRequest(ownerId, otherId string) error {
	filter := bson.M{
		"owner_id": ownerId,
		"other_id": otherId,
	}
	update := bson.M{
		"$set": bson.M{
			"state": 1,
		},
	}
	_, err := friendRequestCollecttion.UpdateOne(context.TODO(), filter, update)
	if err != nil {
		return err
	}

	if err := AddContact(otherId, ownerId); err != nil {
		return err
	}

	err = initSession(ownerId, otherId)
	if err != nil {
		return err
	}

	err = initSession(otherId, ownerId)
	if err != nil {
		return err
	}

	return nil
}

// initSession 同意好友申请后，初始化对应会话列表
func initSession(ownerId, otherId string) error {
	ownerInfo, err := GetUserInfo(ownerId)
	if err != nil {
		return err
	}
	msgId, err := util.MakeSnowflakeID()
	if err != nil {
		return err
	}
	msg := Message{
		MsgId:      msgId,
		OwnerId:    ownerId,
		OtherId:    otherId,
		MsgType:    2,
		Media:      1,
		Content:    "你好",
		Pic:        "",
		Url:        "",
		Desc:       "",
		CreateTime: time.Now().Unix(),
	}
	if _, err = CreateMsg(&msg); err != nil {
		return nil
	}

	session := SessionList{
		OwnerId:        otherId,
		OtherId:        ownerId,
		Nickname:       ownerInfo.Nickname,
		Avator:         ownerInfo.Avator,
		MsgTypt:        2,
		UnreadMsgCount: 1,
		LastTime:       time.Now().Unix(),
		LastMsgId:      msgId,
		LastMsg:        msg,
	}
	_, err = CreateSession(session)

	return err
}
